integer.hpp
namespace type_safe
{
template <typename IntegerT, class Policy>
class integer;
template <class Integer>
using make_signed_t = 'hidden';
template <typename Integer>
constexpr make_signed_t<Integer> make_signed(const Integer& i);
template <typename Integer, class Policy>
constexpr make_signed_t<integer<Integer, Policy>> make_signed(const integer<Integer, Policy>& i);
template <class Integer>
using make_unsigned_t = 'hidden';
template <typename Integer>
constexpr make_unsigned_t<Integer> make_unsigned(const Integer& i);
template <typename Integer, class Policy>
constexpr make_unsigned_t<integer<Integer, Policy>> make_unsigned(const integer<Integer, Policy>& i);
template <typename SignedInteger>
constexpr make_unsigned_t<SignedInteger> abs(const SignedInteger& i);
template <typename SignedInteger, class Policy>
constexpr make_unsigned_t<integer<SignedInteger, Policy>> abs(const integer<SignedInteger, Policy>& i);
template <typename UnsignedInteger>
constexpr UnsignedInteger abs(const UnsignedInteger& i);
template <typename UnsignedInteger, class Policy>
constexpr integer<UnsignedInteger, Policy> abs(const integer<UnsignedInteger, Policy>& i);
//=== Comparison operators ===//
template <typename A, typename B, class Policy>
constexpr bool operator==(const integer<A, Policy>& a, const integer<B, Policy>& b);
template <typename A, typename B, class Policy>
constexpr bool operator==(const A& a, const integer<B, Policy>& b);
template <typename A, class Policy, typename B>
constexpr bool operator==(const integer<A, Policy>& a, const B& b);
template <typename A, typename B, class Policy>
constexpr bool operator!=(const integer<A, Policy>& a, const integer<B, Policy>& b);
template <typename A, typename B, class Policy>
constexpr bool operator!=(const A& a, const integer<B, Policy>& b);
template <typename A, class Policy, typename B>
constexpr bool operator!=(const integer<A, Policy>& a, const B& b);
template <typename A, typename B, class Policy>
constexpr bool operator<(const integer<A, Policy>& a, const integer<B, Policy>& b);
template <typename A, typename B, class Policy>
constexpr bool operator<(const A& a, const integer<B, Policy>& b);
template <typename A, class Policy, typename B>
constexpr bool operator<(const integer<A, Policy>& a, const B& b);
template <typename A, typename B, class Policy>
constexpr bool operator<=(const integer<A, Policy>& a, const integer<B, Policy>& b);
template <typename A, typename B, class Policy>
constexpr bool operator<=(const A& a, const integer<B, Policy>& b);
template <typename A, class Policy, typename B>
constexpr bool operator<=(const integer<A, Policy>& a, const B& b);
template <typename A, typename B, class Policy>
constexpr bool operator>(const integer<A, Policy>& a, const integer<B, Policy>& b);
template <typename A, typename B, class Policy>
constexpr bool operator>(const A& a, const integer<B, Policy>& b);
template <typename A, class Policy, typename B>
constexpr bool operator>(const integer<A, Policy>& a, const B& b);
template <typename A, typename B, class Policy>
constexpr bool operator>=(const integer<A, Policy>& a, const integer<B, Policy>& b);
template <typename A, typename B, class Policy>
constexpr bool operator>=(const A& a, const integer<B, Policy>& b);
template <typename A, class Policy, typename B>
constexpr bool operator>=(const integer<A, Policy>& a, const B& b);
//=== Binary operations ===//
template <typename A, typename B, class Policy>
constexpr 'hidden' operator+(const integer<A, Policy>& a, const integer<B, Policy>& b);
template <typename A, typename B, class Policy>
constexpr 'hidden' operator-(const integer<A, Policy>& a, const integer<B, Policy>& b);
template <typename A, typename B, class Policy>
constexpr 'hidden' operator*(const integer<A, Policy>& a, const integer<B, Policy>& b);
template <typename A, typename B, class Policy>
constexpr 'hidden' operator/(const integer<A, Policy>& a, const integer<B, Policy>& b);
template <typename A, typename B, class Policy>
constexpr 'hidden' operator%(const integer<A, Policy>& a, const integer<B, Policy>& b);
//=== Input/output ===//
template <typename Char, class CharTraits, typename IntegerT, class Policy>
std::basic_istream<Char, CharTraits>& operator>>(std::basic_istream<Char, CharTraits>& in, integer<IntegerT, Policy>& i);
template <typename Char, class CharTraits, typename IntegerT, class Policy>
std::basic_ostream<Char, CharTraits>& operator<<(std::basic_ostream<Char, CharTraits>& out, const integer<IntegerT, Policy>& i);
}
namespace std
{
}
type_safe::integer
template <typename IntegerT, class Policy>
class integer
{
public:
using integer_type = IntegerT;
template <typename T>
constexpr integer(const T& val);
template <typename T>
constexpr integer(const integer<T, Policy>& val);
template <typename T>
integer& operator=(const T& val);
template <typename T>
integer& operator=(const integer<T, Policy>& val);
constexpr operator integer_type() const noexcept;
constexpr integer_type get() const noexcept;
constexpr integer operator+() const;
constexpr integer operator-() const;
integer& operator++();
integer operator++(int);
integer& operator--();
integer operator--(int);
//=== Compound assignment ===//
template <typename T>
integer& operator+=(const integer<T, Policy>& other);
template <typename T>
integer& operator+=(const T& other);
template <typename T>
integer& operator-=(const integer<T, Policy>& other);
template <typename T>
integer& operator-=(const T& other);
template <typename T>
integer& operator*=(const integer<T, Policy>& other);
template <typename T>
integer& operator*=(const T& other);
template <typename T>
integer& operator/=(const integer<T, Policy>& other);
template <typename T>
integer& operator/=(const T& other);
template <typename T>
integer& operator%=(const integer<T, Policy>& other);
template <typename T>
integer& operator%=(const T& other);
};
A type safe integer class.
This is a tiny, no overhead wrapper over a standard integer type. It behaves exactly like the built-in types except that narrowing conversions are not allowed. It also checks against unsigned
under/overflow in debug mode and marks it as undefined for the optimizer otherwise.
A conversion is considered safe if both integer types have the same signedness and the size of the value being converted is less than or equal to the destination size.
Requires: IntegerT
must be an integral type except bool
and char
(use signed char
/unsigned char
). \notes It intentionally does not provide the bitwise operations. \module types
type_safe::integer::integer
(1) template <typename T>
constexpr integer(const T& val);
(2) template <typename T>
constexpr integer(const integer<T, Policy>& val);
Effects: Initializes it with the given value.
Notes: This function does not participate in overload resolution if T
is not an integer type safely convertible to this type.
type_safe::integer::operator=
(1) template <typename T>
integer& operator=(const T& val);
(2) template <typename T>
integer& operator=(const integer<T, Policy>& val);
Effects: Assigns it with the given value.
Notes: This function does not participate in overload resolution if T
is not an integer type safely convertible to this type.
type_safe::integer::operator integer_type
(1) constexpr operator integer_type() const noexcept;
(2) constexpr integer_type get() const noexcept;
Returns: The stored value as the native integer type.
type_safe::integer::operator+
constexpr integer operator+() const;
Returns: The integer type unchanged.
type_safe::integer::operator-
constexpr integer operator-() const;
Returns: The negative integer type.
Requires: The integer type must not be unsigned.
type_safe::integer::operator++
(1) integer& operator++();
(2) integer operator++(int);
Effects: Increments the integer by one.
type_safe::integer::operator--
(1) integer& operator--();
(2) integer operator--(int);
Effects: Decrements the integer by one.
(1) template <typename T>
integer& operator+=(const integer<T, Policy>& other);
(2) template <typename T>
integer& operator+=(const T& other);
(3) template <typename T>
integer& operator-=(const integer<T, Policy>& other);
(4) template <typename T>
integer& operator-=(const T& other);
(5) template <typename T>
integer& operator*=(const integer<T, Policy>& other);
(6) template <typename T>
integer& operator*=(const T& other);
(7) template <typename T>
integer& operator/=(const integer<T, Policy>& other);
(8) template <typename T>
integer& operator/=(const T& other);
(9) template <typename T>
integer& operator%=(const integer<T, Policy>& other);
(10) template <typename T>
integer& operator%=(const T& other);
Effects: Same as the operation on the integer type.
Notes: These functions do not participate in overload resolution, if T
is not an integer type safely convertible to this type.
type_safe::make_signed_t
[types]template <class Integer>
using make_signed_t = 'hidden';
std::make_signed for ts::integer.
type_safe::make_signed
[types]template <typename Integer>
constexpr make_signed_t<Integer> make_signed(const Integer& i);
Returns: A new integer of the corresponding signed integer type.
Requires: The value of i
must fit into signed type.
type_safe::make_signed
[types]template <typename Integer, class Policy>
constexpr make_signed_t<integer<Integer, Policy>> make_signed(const integer<Integer, Policy>& i);
Returns: A new ts::integer of the corresponding signed integer type.
Requires: The value of i
must fit into signed type.
type_safe::make_unsigned_t
[types]template <class Integer>
using make_unsigned_t = 'hidden';
std::make_unsigned for ts::integer.
type_safe::make_unsigned
[types]template <typename Integer>
constexpr make_unsigned_t<Integer> make_unsigned(const Integer& i);
Returns: A new integer of the corresponding unsigned integer type.
Requires: The value of i
must not be negative.
type_safe::make_unsigned
[types]template <typename Integer, class Policy>
constexpr make_unsigned_t<integer<Integer, Policy>> make_unsigned(const integer<Integer, Policy>& i);
Returns: A new ts::integer of the corresponding unsigned integer type.
Requires: The value of i
must not be negative.
type_safe::abs
[types]template <typename SignedInteger>
constexpr make_unsigned_t<SignedInteger> abs(const SignedInteger& i);
Returns: The absolute value of a built-in signed integer. It will be changed to the unsigned return type as well.
type_safe::abs
[types]template <typename SignedInteger, class Policy>
constexpr make_unsigned_t<integer<SignedInteger, Policy>> abs(const integer<SignedInteger, Policy>& i);
Returns: The absolute value of an ts::integer.
type_safe::abs
[types]template <typename UnsignedInteger>
constexpr UnsignedInteger abs(const UnsignedInteger& i);
Returns: i
unchanged.
Notes: This is an optimization of abs()
for unsigned integer types.
type_safe::abs
[types]template <typename UnsignedInteger, class Policy>
constexpr integer<UnsignedInteger, Policy> abs(const integer<UnsignedInteger, Policy>& i);
Returns: i
unchanged.
Notes: This is an optimization of abs()
for unsigned integer types.
(1) template <typename A, typename B, class Policy>
constexpr bool operator==(const integer<A, Policy>& a, const integer<B, Policy>& b);
(2) template <typename A, typename B, class Policy>
constexpr bool operator==(const A& a, const integer<B, Policy>& b);
(3) template <typename A, class Policy, typename B>
constexpr bool operator==(const integer<A, Policy>& a, const B& b);
(4) template <typename A, typename B, class Policy>
constexpr bool operator!=(const integer<A, Policy>& a, const integer<B, Policy>& b);
(5) template <typename A, typename B, class Policy>
constexpr bool operator!=(const A& a, const integer<B, Policy>& b);
(6) template <typename A, class Policy, typename B>
constexpr bool operator!=(const integer<A, Policy>& a, const B& b);
(7) template <typename A, typename B, class Policy>
constexpr bool operator<(const integer<A, Policy>& a, const integer<B, Policy>& b);
(8) template <typename A, typename B, class Policy>
constexpr bool operator<(const A& a, const integer<B, Policy>& b);
(9) template <typename A, class Policy, typename B>
constexpr bool operator<(const integer<A, Policy>& a, const B& b);
(10) template <typename A, typename B, class Policy>
constexpr bool operator<=(const integer<A, Policy>& a, const integer<B, Policy>& b);
(11) template <typename A, typename B, class Policy>
constexpr bool operator<=(const A& a, const integer<B, Policy>& b);
(12) template <typename A, class Policy, typename B>
constexpr bool operator<=(const integer<A, Policy>& a, const B& b);
(13) template <typename A, typename B, class Policy>
constexpr bool operator>(const integer<A, Policy>& a, const integer<B, Policy>& b);
(14) template <typename A, typename B, class Policy>
constexpr bool operator>(const A& a, const integer<B, Policy>& b);
(15) template <typename A, class Policy, typename B>
constexpr bool operator>(const integer<A, Policy>& a, const B& b);
(16) template <typename A, typename B, class Policy>
constexpr bool operator>=(const integer<A, Policy>& a, const integer<B, Policy>& b);
(17) template <typename A, typename B, class Policy>
constexpr bool operator>=(const A& a, const integer<B, Policy>& b);
(18) template <typename A, class Policy, typename B>
constexpr bool operator>=(const integer<A, Policy>& a, const B& b);
Returns: The result of the comparison of the stored integer value in the ts::integer.
Notes: These functions do not participate in overload resolution unless A
and B
are both integer types.
(1) template <typename A, typename B, class Policy>
constexpr 'hidden' operator+(const integer<A, Policy>& a, const integer<B, Policy>& b);
(2) template <typename A, typename B, class Policy>
constexpr 'hidden' operator-(const integer<A, Policy>& a, const integer<B, Policy>& b);
(3) template <typename A, typename B, class Policy>
constexpr 'hidden' operator*(const integer<A, Policy>& a, const integer<B, Policy>& b);
(4) template <typename A, typename B, class Policy>
constexpr 'hidden' operator/(const integer<A, Policy>& a, const integer<B, Policy>& b);
(5) template <typename A, typename B, class Policy>
constexpr 'hidden' operator%(const integer<A, Policy>& a, const integer<B, Policy>& b);
Returns: The result of the binary operation of the stored integer value in the ts::integer. The type is a ts::integer of the bigger integer type.
Notes: These functions do not participate in overload resolution, unless A
and B
are both integer types.
type_safe::operator>>
[types]template <typename Char, class CharTraits, typename IntegerT, class Policy>
std::basic_istream<Char, CharTraits>& operator>>(std::basic_istream<Char, CharTraits>& in, integer<IntegerT, Policy>& i);
Effects: Reads an integer from the std::istream and assigns it to the given ts::integer.
type_safe::operator<<
template <typename Char, class CharTraits, typename IntegerT, class Policy>
std::basic_ostream<Char, CharTraits>& operator<<(std::basic_ostream<Char, CharTraits>& out, const integer<IntegerT, Policy>& i);
Effects: Converts the given ts::integer to the underlying integer type and writes it to th std::ostream. \module types